﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using DomainDriver.CommonUtilities.Collections;
using DomainDriver.CommonUtilities.Reflectors;
using DomainDriver.DomainModeling.Attributes;
using DomainDriver.DomainModeling.DomainObjects;
using DomainDriver.DomainModeling.Exceptions;

namespace DomainDriver.DomainModeling.Example.DomainObjects
{
    public partial class DummyDomainObject : KeyedDomainObjectBase<Guid, DummyDomainObject>
    {
        private int m_Index;
        private string m_Name;
        private Nullable<Guid> m_Parent;
        private Dictionary<Guid, DummyDomainObjectRelation> m_Children;

        public DummyDomainObject(Nullable<Guid> parentId)
        {
            m_Key = Guid.NewGuid();
            m_Index = 0;
            m_Name = string.Empty;
            m_Parent = parentId;
            m_Children = new Dictionary<Guid, DummyDomainObjectRelation>();
        }

        public DummyDomainObject()
            : this(null)
        {
            // do nothing
        }

        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Index
        {
            get { return m_Index; }
            set { m_Index = value; }
        }

        [Unique]
        [NotNull]
        [NotEqualToValue("")]
        public string Name
        {
            get { return m_Name; }
            set { m_Name = value; }
        }

        public Nullable<Guid> Parent
        {
            get { return m_Parent; }
            set { m_Parent = value; }
        }

        public IList<Guid> Children
        {
            get { return new List<Guid>(m_Children.Keys); }
        }

        public void AddChild(Guid childId)
        {
            if (m_Children.ContainsKey(childId))
            {
                throw new ApplicationException();
            }
            m_Children.Add(childId, new DummyDomainObjectRelation(m_Key, childId));
        }

        public void RemoveChild(Guid childId)
        {
            if (!m_Children.ContainsKey(childId))
            {
                throw new ApplicationException();
            }
            m_Children.Remove(childId);
        }

        #region DomainObject Methods

        public override DummyDomainObject Copy()
        {
            DummyDomainObject newObject = new DummyDomainObject();
            CopyTo(newObject);
            return newObject;
        }

        public override void CopyTo(DummyDomainObject otherObject)
        {
            ClassReflector.CopyValueTypesAndStrings<DummyDomainObject>(this, otherObject);
            CopyDictionaryToOtherInPlace<Guid, DummyDomainObjectRelation>(otherObject, (DummyDomainObjectRelation rel) => rel.ChildId, (DummyDomainObject obj) => obj.m_Children);
        }

        public override bool Equals(DummyDomainObject otherObject)
        {
            if (!ClassReflector.CheckEqualityForValueTypesAndStrings<DummyDomainObject>(this, otherObject))
            { return false; }
            if (!CollectionUtilities.AreUnorderedDictionariesEqual<Guid, DummyDomainObjectRelation>(m_Children, otherObject.m_Children))
            { return false; }
            return true;
        }

        #endregion
    }
}